﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace SpaceShooter.Common
{
    /// <summary>
    /// The DrawableGameObject manages everything that is needed to draw a individual model.
    /// It manages position, velocity (the direction of movement plus the velocity amount) and
    /// the up direction.
    /// It enables derived classes to influence these properties by player interaction and
    /// physics simulation.
    /// </summary>
    public class DrawableGameObject
    {
        private string modelName;

        public DrawableGameObject(IGameScreen gameScreen, string modelName)
        {
            this.GameScreen = gameScreen;
            this.InitialModelRotation = Matrix.Identity;
            this.modelName = modelName;
            this.Direction = Vector3.One;
            this.Speed = 0;
            this.RemoveFlag = false;
            this.Up = Vector3.Up;
        }

        public IGameScreen GameScreen { get; private set; }

        public Matrix PositionMatrix { get; private set; }
        /*
        public ModelMeshCollection Meshes
        {
            get { return this.model.Meshes; }
        }
        */
        protected Matrix InitialModelRotation { get; set; }

        public Vector3 Direction { get; private set; }

        public Vector3 Position { get; private set; }

        public Vector3 Up { get; private set; }

        public float Speed { get; private set; }

        public Vector3 Velocity
        {
            get { return this.Direction * this.Speed; }
        }

        public DrawableGameObject SetDirection(Vector3 value)
        {
            this.Direction = value;
            this.Direction.Normalize();

            return this;
        }

        public DrawableGameObject SetSpeed(float value)
        {
            this.Speed = value;

            return this;
        }

        public DrawableGameObject SetPosition(Vector3 pos)
        {
            this.Position = pos;
            this.BuildMatrix();

            return this;
        }

        public DrawableGameObject SetUpVector(Vector3 up)
        {
            this.Up = up;

            return this;
        }

        public DrawableGameObject AddPosition(Vector3 pos)
        {
            this.Position += pos;
            this.BuildMatrix();

            return this;
        }

        public virtual void Initialize()
        {
        }

        public virtual void Update(GameTime gameTime)
        {
            var newPosition = this.Position + this.Direction * this.Speed * (float)gameTime.ElapsedGameTime.TotalSeconds;

            if (this.GameScreen.GameField.IsInside(newPosition))
            {
                this.Position = newPosition;
                this.BuildMatrix();
            }
        }

        private void BuildMatrix()
        {
            this.PositionMatrix = 
                this.InitialModelRotation *
                Matrix.CreateTranslation(this.Position);
        }

        public bool RemoveFlag { get; set; }

        public Model Model
        {
            get { return this.GameScreen.Game.Content.Load<Model>(this.modelName); }
        }

        public BoundingSphere GetBoundingSphere()
        {
            var bs = this.Model.Meshes[0].BoundingSphere;
            bs = bs.Transform(this.PositionMatrix);
            return bs;
        }
    }
}